<script setup lang="ts">
import { nextTick, onMounted, onUnmounted, ref } from 'vue';
import { useRoute } from 'vue-router';
import { Button, Card, Empty, Space, Table, Tag } from 'ant-design-vue';
import { useEcharts } from '@/hooks/common/echarts';
import type { SSEClient } from '@/utils/sse';
import { createSSEClient } from '@/utils/sse';

const route = useRoute();
const ip = route.query.ip as string;
const port = route.query.port as string;

const loading = ref(true);
const nodeInfo = ref<any>(null);
const jobs = ref<any[]>([]);
const resource = ref<{ cpu: string; memory: string }>({ cpu: '', memory: '' });
const logs = ref<string[]>([]);
const logContainer = ref<HTMLElement>();
const isConnected = ref(false);
const connectionStatus = ref('disconnected'); // disconnected, connecting, connected, error

// 日志滚动相关状态
const autoScroll = ref(true); // 是否自动滚动到最新日志
const showScrollToTop = ref(false); // 是否显示"回到最新"按钮
const unreadCount = ref(0); // 未读日志数量

// 资源监控相关状态
const resourceConnected = ref(false);
const resourceConnectionStatus = ref('disconnected');
const resourceUsage = ref({
  cpu: 0,
  memory: 0,
  cpuPercent: '0%',
  memoryPercent: '0%',
  totalMemoryMB: 0,
  usedMemoryMB: 0,
  jvm: {
    usedMemoryMB: 0,
    maxMemoryMB: 0,
    usagePercent: '0%'
  },
  systemLoadAverage: 0,
  availableProcessors: 0
});
const resourceHistory = ref<any[]>([]);

// ECharts 图表配置
const { domRef: chartDomRef, updateOptions } = useEcharts(() => ({
  animation: false, // 关闭全局动画，避免数据更新时的闪烁效果
  animationThreshold: 2000, // 提高动画阈值
  progressive: 400, // 渐进式渲染
  progressiveThreshold: 3000, // 渐进式渲染阈值
  title: {
    text: '资源使用率趋势',
    left: 'center',
    textStyle: {
      fontSize: 12,
      fontWeight: 'normal'
    }
  },
  tooltip: {
    trigger: 'axis',
    textStyle: {
      fontSize: 11
    },
    axisPointer: {
      type: 'cross',
      label: {
        backgroundColor: '#6a7985'
      }
    },
    formatter: (params: any) => {
      let result = `时间: ${params[0].axisValue}<br/>`;
      params.forEach((param: any) => {
        result += `${param.seriesName}: ${param.value.toFixed(1)}%<br/>`;
      });
      return result;
    }
  },
  legend: {
    data: ['CPU使用率', '内存使用率'],
    bottom: 5,
    textStyle: {
      fontSize: 11
    }
  },
  grid: {
    left: '3%',
    right: '4%',
    bottom: '12%',
    top: '12%',
    containLabel: true
  },
  xAxis: {
    type: 'category',
    boundaryGap: false,
    data: [] as string[],
    axisLabel: {
      rotate: 45,
      fontSize: 9
    }
  },
  yAxis: {
    type: 'value',
    max: 100,
    min: 0,
    axisLabel: {
      formatter: '{value}%',
      fontSize: 9
    }
  },
  series: [
    {
      name: 'CPU使用率',
      type: 'line',
      smooth: true,
      symbol: 'circle',
      symbolSize: 3,
      animation: false, // 关闭系列动画
      lineStyle: {
        width: 1.5,
        color: '#1890ff'
      },
      itemStyle: {
        color: '#1890ff'
      },
      areaStyle: {
        color: {
          type: 'linear',
          x: 0,
          y: 0,
          x2: 0,
          y2: 1,
          colorStops: [
            {
              offset: 0,
              color: 'rgba(24, 144, 255, 0.3)'
            },
            {
              offset: 1,
              color: 'rgba(24, 144, 255, 0.05)'
            }
          ]
        }
      },
      data: [] as number[]
    },
    {
      name: '内存使用率',
      type: 'line',
      smooth: true,
      symbol: 'circle',
      symbolSize: 3,
      animation: false, // 关闭系列动画
      lineStyle: {
        width: 1.5,
        color: '#52c41a'
      },
      itemStyle: {
        color: '#52c41a'
      },
      areaStyle: {
        color: {
          type: 'linear',
          x: 0,
          y: 0,
          x2: 0,
          y2: 1,
          colorStops: [
            {
              offset: 0,
              color: 'rgba(82, 196, 26, 0.3)'
            },
            {
              offset: 1,
              color: 'rgba(82, 196, 26, 0.05)'
            }
          ]
        }
      },
      data: [] as number[]
    }
  ]
}));

// 使用SSEClient管理连接
let logSSEClient: SSEClient | null = null;
let resourceSSEClient: SSEClient | null = null;

// 组件挂载时初始化
onMounted(() => {
  fetchNodeDetail();
  connectLogStream();
  connectResourceStream();
});

// 组件卸载时清理
onUnmounted(() => {
  disconnectLogStream();
  disconnectResourceStream();
});

async function fetchNodeDetail() {
  try {
    loading.value = true;
    // 模拟获取节点详情
    nodeInfo.value = {
      ip: ip || 'localhost',
      port: port || '8080',
      status: 'online',
      desc: '计算节点'
    };

    // 模拟获取任务列表
    jobs.value = [
      { id: 'job-001', name: '数据处理任务', status: 'running', startTime: '2024-01-01 10:00:00' },
      { id: 'job-002', name: '模型训练任务', status: 'waiting', startTime: '2024-01-01 11:00:00' }
    ];
  } catch (error) {
    console.error('获取节点详情失败:', error);
  } finally {
    loading.value = false;
  }
}

// 监听日志容器滚动事件
function handleLogScroll() {
  if (!logContainer.value) return;

  const { scrollTop, scrollHeight, clientHeight } = logContainer.value;
  const isAtBottom = scrollTop + clientHeight >= scrollHeight - 5; // 容许5px的误差

  if (isAtBottom && !autoScroll.value) {
    // 用户滚动到了底部（最新日志位置），重新启用自动滚动
    autoScroll.value = true;
    showScrollToTop.value = false;
    unreadCount.value = 0;
  } else if (!isAtBottom && autoScroll.value) {
    // 用户滚动离开了底部，禁用自动滚动
    autoScroll.value = false;
    showScrollToTop.value = true;
  }
}

// 滚动到最新日志（底部）
function scrollToLatest() {
  if (logContainer.value) {
    logContainer.value.scrollTo({
      top: logContainer.value.scrollHeight,
      behavior: 'smooth'
    });
    autoScroll.value = true;
    showScrollToTop.value = false;
    unreadCount.value = 0;
  }
}

// 添加日志并处理滚动
function addLogMessage(message: string) {
  logs.value.push(message); // 新日志添加到数组末尾

  // 保持最多100条日志
  if (logs.value.length > 100) {
    logs.value = logs.value.slice(-100); // 保留最后100条
  }

  // 如果启用了自动滚动，则滚动到最新日志（底部）
  if (autoScroll.value) {
    nextTick(() => {
      if (logContainer.value) {
        logContainer.value.scrollTop = logContainer.value.scrollHeight;
      }
    });
  } else {
    // 如果没有启用自动滚动，增加未读计数
    unreadCount.value += 1;
  }
}

function connectLogStream() {
  if (logSSEClient) {
    logSSEClient.disconnect();
  }

  // 根据节点的 IP 和 PORT 动态构建请求地址
  const nodeIp = ip || 'localhost';
  const nodePort = port || '8080';
  const url = `/proxy/node/logs/stream?ip=${encodeURIComponent(nodeIp)}&port=${encodeURIComponent(nodePort)}`;

  // 创建SSE客户端实例
  logSSEClient = createSSEClient(url, {
    maxReconnectAttempts: 5,
    reconnectDelay: 3000,
    autoReconnect: true
  });

  // 设置状态变化监听器
  logSSEClient.setStatusChangeListener(status => {
    connectionStatus.value = status;
    isConnected.value = status === 'connected';
  });

  // 设置事件处理器
  logSSEClient.on('connected', data => {
    console.log('日志流连接成功:', data);
    addLogMessage(`[${new Date().toLocaleTimeString()}] 已连接到节点 ${ip}:${port} 的日志流`);
  });

  logSSEClient.on('node-log', data => {
    const logMessage = `[${data.timestamp}] [${data.level}] ${data.message}`;
    addLogMessage(logMessage);
  });

  logSSEClient.on('realtime', data => {
    resource.value.cpu = data.cpuPercent || '0%';
    resource.value.memory = data.memoryPercent || '0%';
  });

  // 建立连接
  logSSEClient.connect();
}

// 连接资源监控流
function connectResourceStream() {
  if (resourceSSEClient) {
    resourceSSEClient.disconnect();
  }

  // 根据节点的 IP 和 PORT 动态构建请求地址
  const nodeIp = ip || 'localhost';
  const nodePort = port || '8080';
  const url = `/proxy/resource/stream?ip=${encodeURIComponent(nodeIp)}&port=${encodeURIComponent(nodePort)}`;

  // 创建SSE客户端实例
  resourceSSEClient = createSSEClient(url, {
    maxReconnectAttempts: 5,
    reconnectDelay: 3000,
    autoReconnect: true
  });

  // 设置状态变化监听器
  resourceSSEClient.setStatusChangeListener(status => {
    resourceConnectionStatus.value = status;
    resourceConnected.value = status === 'connected';
  });

  // 设置事件处理器
  resourceSSEClient.on('connected', data => {
    console.log('资源监控连接成功:', data);
  });

  resourceSSEClient.on('resource', data => {
    // 更新资源使用率
    resourceUsage.value = {
      cpu: data.cpu * 100 || 0,
      memory: data.memory * 100 || 0,
      cpuPercent: data.cpuPercent || '0%',
      memoryPercent: data.memoryPercent || '0%',
      totalMemoryMB: data.totalMemoryMB || 0,
      usedMemoryMB: data.usedMemoryMB || 0,
      jvm: data.jvm || resourceUsage.value.jvm,
      systemLoadAverage: data.systemLoadAverage || 0,
      availableProcessors: data.availableProcessors || 0
    };

    // 🌟 参考ECharts示例：使用相同的滚动窗口机制处理实时数据
    const MAX_DATA_POINTS = 20; // 与模拟数据保持一致
    const newTimestamp = new Date().toLocaleTimeString().replace(/^\D*/, '');

    // 滚动窗口：移除最老数据，添加最新数据
    if (resourceHistory.value.length >= MAX_DATA_POINTS) {
      resourceHistory.value.shift(); // 移除最老的数据点
    }

    // 添加新数据点
    resourceHistory.value.push({
      timestamp: newTimestamp,
      cpu: resourceUsage.value.cpu,
      memory: resourceUsage.value.memory
    });

    // 立即更新图表（参考示例的实时性）
    updateChartData();
  });

  resourceSSEClient.on('error', data => {
    console.error('资源监控错误:', data.message);
  });

  // 建立连接
  resourceSSEClient.connect();
}

function disconnectLogStream() {
  if (logSSEClient) {
    logSSEClient.disconnect();
    logSSEClient = null;
  }
}

function disconnectResourceStream() {
  if (resourceSSEClient) {
    resourceSSEClient.disconnect();
    resourceSSEClient = null;
  }
}

function clearLogs() {
  logs.value = [];
  unreadCount.value = 0;
  autoScroll.value = true;
  showScrollToTop.value = false;
}

function getConnectionStatusColor() {
  switch (connectionStatus.value) {
    case 'connected':
      return 'success';
    case 'connecting':
      return 'processing';
    case 'error':
      return 'error';
    default:
      return 'default';
  }
}

function getResourceConnectionStatusColor() {
  switch (resourceConnectionStatus.value) {
    case 'connected':
      return 'success';
    case 'connecting':
      return 'processing';
    case 'error':
      return 'error';
    default:
      return 'default';
  }
}

function getLogLevelClass(message: string): string {
  if (message.includes('[ERROR]')) return 'log-error';
  if (message.includes('[WARN]')) return 'log-warn';
  if (message.includes('[DEBUG]')) return 'log-debug';
  return 'log-info';
}

function getJobStatusColor(status: string): string {
  const map: Record<string, string> = { running: 'success', waiting: 'warning', failed: 'error' };
  return map[status] || 'default';
}

function getJobStatusLabel(status: string): string {
  const labelMap: Record<string, string> = { running: '运行中', waiting: '等待', failed: '失败' };
  return labelMap[status] || status;
}

// 获取CPU使用率的颜色

// 获取内存使用率的颜色

// 获取JVM内存颜色

// 已移除防抖机制 - 参考ECharts示例直接更新图表

// 更新图表数据 - 参考ECharts动态示例，实现真正的实时滚动
function updateChartData() {
  if (resourceHistory.value.length === 0) return;

  const timestamps = resourceHistory.value.map(item => item.timestamp);
  const cpuData = resourceHistory.value.map(item => Number(item.cpu.toFixed(1)));
  const memoryData = resourceHistory.value.map(item => Number(item.memory.toFixed(1)));

  // 参考ECharts动态示例，使用updateOptions进行高效更新
  // 只更新数据部分，保持其他配置不变
  updateOptions(opts => {
    // 直接修改原始配置对象的数据部分
    opts.xAxis.data = timestamps;
    opts.series[0].data = cpuData;
    opts.series[1].data = memoryData;
    return opts;
  });
}

// 移除模拟数据更新函数 - 只使用真实的SSE数据
// function startMockDataUpdate() {
//   // 设置固定的数据窗口大小
//   const MAX_DATA_POINTS = 20; // 显示最近20个数据点

//   mockDataTimer = setInterval(() => {
//     // 生成新的时间戳（参考示例格式）
//     const newTimestamp = new Date().toLocaleTimeString().replace(/^\D*/, '');

//     // 模拟新的资源数据
//     const newCpuValue = +(Math.random() * 80 + 10).toFixed(1); // 10.0-90.0%
//     const newMemoryValue = +(Math.random() * 70 + 20).toFixed(1); // 20.0-90.0%

//     // 更新当前资源状态
//     resourceUsage.value.cpu = newCpuValue;
//     resourceUsage.value.memory = newMemoryValue;
//     resourceUsage.value.cpuPercent = `${newCpuValue}%`;
//     resourceUsage.value.memoryPercent = `${newMemoryValue}%`;

//     // 🌟 参考示例：使用滚动窗口机制 - shift() 移除最老数据，push() 添加最新数据
//     if (resourceHistory.value.length >= MAX_DATA_POINTS) {
//       resourceHistory.value.shift(); // 移除最老的数据点
//     }

//     // 添加新数据点（始终添加到末尾）
//     resourceHistory.value.push({
//       timestamp: newTimestamp,
//       cpu: newCpuValue,
//       memory: newMemoryValue
//     });

//     // 立即更新图表（参考示例的实时性）
//     updateChartData();

//     console.log(`📊 实时滚动更新: CPU ${newCpuValue}%, Memory ${newMemoryValue}% [${newTimestamp}]`);
//   }, 2100); // 参考示例：2.1秒间隔
// }

onMounted(() => {
  fetchNodeDetail();
  connectLogStream();
  connectResourceStream(); // 连接资源监控流

  // 监听日志容器滚动事件
  if (logContainer.value) {
    logContainer.value.addEventListener('scroll', handleLogScroll);
  }

  // 初始化图表数据（等待SSE数据）
  setTimeout(() => {
    // 不再初始化模拟数据，等待真实的SSE数据
    console.log('等待SSE资源数据...');
  }, 1000);
});

onUnmounted(() => {
  disconnectLogStream();
  disconnectResourceStream(); // 断开资源监控流

  // 移除滚动监听
  if (logContainer.value) {
    logContainer.value.removeEventListener('scroll', handleLogScroll);
  }
});

const jobColumns = [
  { title: '作业ID', dataIndex: 'id', key: 'id' },
  { title: '作业名称', dataIndex: 'name', key: 'name' },
  {
    title: '状态',
    dataIndex: 'status',
    key: 'status'
  },
  { title: '开始时间', dataIndex: 'startTime', key: 'startTime' }
];
</script>

<template>
  <div class="node-detail-page">
    <!-- 顶部信息栏 -->
    <ACard size="small" class="header-section">
      <!-- 左侧：节点信息 + 详细资源监控 -->
      <div class="left-panel">
        <!-- 节点基本信息 -->
        <div class="node-info">
          <div class="info-item">
            <span class="label">节点：</span>
            <span class="value">{{ nodeInfo?.ip }}:{{ nodeInfo?.port }}</span>
          </div>
          <div class="info-item">
            <span class="label">状态：</span>
            <Tag :color="nodeInfo?.status === 'online' ? 'success' : 'error'" size="small">
              {{ nodeInfo?.status === 'online' ? '在线' : '离线' }}
            </Tag>
          </div>
          <div class="info-item">
            <span class="label">描述：</span>
            <span class="value">{{ nodeInfo?.desc || '-' }}</span>
          </div>
        </div>

        <!-- 详细资源监控面板 -->
        <div class="resource-detail-panel">
          <div class="resource-panel-header">
            <span class="panel-title">资源监控</span>
            <Tag :color="getResourceConnectionStatusColor()" size="small">
              {{ resourceConnected ? '已连接' : '未连接' }}
            </Tag>
          </div>

          <!-- 资源使用率折线图 -->
          <div class="resource-chart-container">
            <div ref="chartDomRef" class="resource-chart"></div>
          </div>

          <!-- 资源监控控制 -->
          <div class="resource-controls">
            <Button size="small" type="primary" :disabled="resourceConnected" @click="connectResourceStream">
              连接资源流
            </Button>
            <Button size="small" :disabled="!resourceConnected" @click="disconnectResourceStream">断开连接</Button>
          </div>
        </div>
      </div>
    </ACard>

    <!-- 主要内容区域 -->
    <div class="main-content">
      <!-- 左侧：任务列表 -->
      <div class="jobs-section">
        <Card title="运行中的任务" size="small" class="jobs-card">
          <Table :columns="jobColumns" :data-source="jobs" :pagination="false" size="small">
            <template #bodyCell="{ column, text }">
              <template v-if="column.dataIndex === 'status'">
                <Tag :color="getJobStatusColor(text)" size="small">
                  {{ getJobStatusLabel(text) }}
                </Tag>
              </template>
            </template>
            <template #emptyText>
              <Empty description="暂无运行中的任务" :image-style="{ height: '60px' }" />
            </template>
          </Table>
        </Card>
      </div>

      <!-- 右侧：实时日志 -->
      <div class="logs-section">
        <Card title="实时日志" size="small" class="log-card">
          <template #extra>
            <Space>
              <Tag :color="getConnectionStatusColor()" size="small">
                {{
                  connectionStatus === 'connected'
                    ? '已连接'
                    : connectionStatus === 'connecting'
                      ? '连接中'
                      : connectionStatus === 'error'
                        ? '连接失败'
                        : '未连接'
                }}
              </Tag>
              <Button size="small" type="primary" :disabled="isConnected" @click="connectLogStream">连接</Button>
              <Button size="small" :disabled="!isConnected" @click="disconnectLogStream">断开</Button>
              <Button size="small" @click="clearLogs">清空</Button>
            </Space>
          </template>

          <div class="log-wrapper">
            <div ref="logContainer" class="log-container" @scroll="handleLogScroll">
              <div v-if="logs.length === 0" class="log-empty">暂无日志数据</div>
              <div v-for="(log, index) in logs" :key="index" class="log-line" :class="[getLogLevelClass(log)]">
                {{ log }}
              </div>
            </div>

            <!-- 固定的"回到最新"按钮 -->
            <div v-if="showScrollToTop" class="scroll-to-latest-btn">
              <Button type="primary" size="small" shape="round" class="latest-btn" @click="scrollToLatest">
                <template #icon>
                  <svg width="14" height="14" viewBox="0 0 24 24" fill="none" xmlns="http://www.w3.org/2000/svg">
                    <path
                      d="M12 20L12 4M12 20L18 14M12 20L6 14"
                      stroke="currentColor"
                      stroke-width="2"
                      stroke-linecap="round"
                      stroke-linejoin="round"
                    />
                  </svg>
                </template>
                回到最新
                <span v-if="unreadCount > 0" class="unread-badge">{{ unreadCount > 99 ? '99+' : unreadCount }}</span>
              </Button>
            </div>
          </div>
        </Card>
      </div>
    </div>
  </div>
</template>

<style scoped>
.node-detail-page {
  padding: 12px;
  /* background-color: #f5f5f5; */
  height: calc(100vh - 200px);
  display: flex;
  flex-direction: column;
  overscroll-behavior-y: none;
}

/* 顶部区域 */
.header-section {
  /* display: flex;
  justify-content: space-between;
  align-items: flex-start; */
  margin-bottom: 12px;
  /* background: white; */
  /* padding: 16px; */
  border-radius: 12px;
  box-shadow: 0 2px 8px rgba(0, 0, 0, 0.06);
  gap: 20px;
}

/* 左侧面板 */
.left-panel {
  flex: 1;
  display: flex;
  flex-direction: column;
  gap: 16px;
}
.node-info {
  display: flex;
  align-items: center;
  gap: 20px;
  padding-bottom: 12px;
  border-bottom: 1px solid #f0f0f0;
}

.info-item {
  display: flex;
  align-items: center;
  gap: 6px;
}

.label {
  font-weight: 500;
  color: #666;
  font-size: 13px;
}

.dark .label {
  color: #cbd5e1;
}

.value {
  color: #333;
  font-weight: 600;
  font-size: 13px;
}

.dark .value {
  color: #f8fafc;
}

/* 详细资源监控面板 */
.resource-detail-panel {
  display: flex;
  flex-direction: column;
  gap: 12px;
}

.resource-panel-header {
  display: flex;
  justify-content: space-between;
  align-items: center;
}

.panel-title {
  font-size: 14px;
  font-weight: 600;
  /* color: #333; */
}

/* 图表容器样式 */
.resource-chart-container {
  border: 1px solid #f0f0f0;
  border-radius: 8px;
  transition: all 0.2s ease;
}

.resource-chart {
  height: 200px;
  width: 100%;
}

/* 资源概览样式 */
.resource-summary {
  display: grid;
  grid-template-columns: repeat(3, 1fr);
  gap: 16px;
}

.summary-item {
  background: #fafafa;
  border: 1px solid #f0f0f0;
  border-radius: 8px;
  padding: 16px;
  text-align: center;
  transition: all 0.2s ease;
}

.summary-item:hover {
  background: #f5f5f5;
  border-color: #d9d9d9;
}

.summary-label {
  font-size: 14px;
  color: #666;
  margin-bottom: 8px;
  font-weight: 500;
}

.summary-value {
  font-size: 20px;
  font-weight: 600;
  margin-bottom: 4px;
}

.summary-detail {
  font-size: 12px;
  color: #999;
}

.resource-controls {
  display: flex;
  gap: 8px;
  justify-content: flex-end;
}

/* 右侧紧凑监控 */
.right-monitor {
  display: flex;
  flex-direction: column;
  align-items: flex-end;
  gap: 12px;
  min-width: 200px;
}

.monitor-header {
  display: flex;
  align-items: center;
}

.monitor-title {
  font-size: 14px;
  font-weight: 500;
  color: #666;
}

.compact-monitors {
  display: flex;
  gap: 16px;
}

.compact-item {
  display: flex;
  flex-direction: column;
  align-items: center;
  gap: 8px;
}

.compact-info {
  text-align: center;
}

.compact-value {
  font-size: 12px;
  font-weight: 600;
  color: #333;
}

.compact-label {
  font-size: 11px;
  color: #999;
  margin-top: 2px;
}

/* 主要内容区域 */
.main-content {
  flex: 1;
  display: flex;
  gap: 12px;
  min-height: 0;
}

.jobs-section {
  width: 35%;
  display: flex;
  flex-direction: column;
}

.jobs-card {
  height: 100%;
  border-radius: 8px;
  box-shadow: 0 2px 8px rgba(0, 0, 0, 0.06);
}

.jobs-card :deep(.ant-card-body) {
  height: calc(100% - 37px);
  padding: 4px;
  font-size: 12px;
}

.logs-section {
  width: 65%;
  display: flex;
  flex-direction: column;
}

.log-card {
  height: 100%;
  border-radius: 8px;
  box-shadow: 0 2px 8px rgba(0, 0, 0, 0.06);
}

.log-card :deep(.ant-card-body) {
  height: calc(100% - 37px);
  padding: 4px;
  position: relative;
  font-size: 12px;
}

.log-wrapper {
  height: 100%;
  position: relative;
}

.log-container {
  height: 100%;
  overflow-y: auto;
  /* background: #f8f9fa; */
  /* border: 1px solid #e9ecef; */
  /* border-radius: 4px; */
  padding: 10px;
  font-family: 'Consolas', 'Monaco', 'Courier New', monospace;
  font-size: 9px;
  line-height: 1.2;
}

.log-empty {
  color: #999;
  text-align: center;
  padding: 40px 0;
}

.log-line {
  margin-bottom: 2px;
  white-space: pre-wrap;
  word-break: break-all;
  padding: 1px 0;
}

.log-info {
  color: #333;
}

.dark .log-info {
  color: #f8fafc;
}
.log-debug {
  color: #6c757d;
}
.log-warn {
  color: #fd7e14;
}
.log-error {
  color: #dc3545;
  font-weight: 500;
}

/* 固定按钮样式 */
.scroll-to-latest-btn {
  position: absolute;
  top: 20px;
  right: 20px;
  z-index: 1000;
  background: rgba(255, 255, 255, 0.1);
  backdrop-filter: blur(10px);
  border-radius: 20px;
  padding: 4px;
}

.latest-btn {
  display: flex;
  align-items: center;
  gap: 6px;
  box-shadow: 0 4px 12px rgba(24, 144, 255, 0.3);
  border: none !important;
  font-weight: 500;
  animation: slideIn 0.3s ease-out;
  background: linear-gradient(135deg, #1890ff, #096dd9) !important;
  color: white !important;
  height: 32px;
  padding: 0 12px;
}

.latest-btn:hover {
  box-shadow: 0 6px 16px rgba(24, 144, 255, 0.4) !important;
  transform: translateY(-1px) !important;
  background: linear-gradient(135deg, #40a9ff, #1890ff) !important;
}

.unread-badge {
  background: #ff4d4f;
  color: white;
  border-radius: 10px;
  padding: 2px 6px;
  font-size: 11px;
  font-weight: 600;
  margin-left: 4px;
  min-width: 18px;
  text-align: center;
  line-height: 1;
}

@keyframes slideIn {
  from {
    opacity: 0;
    transform: translateY(-10px);
  }
  to {
    opacity: 1;
    transform: translateY(0);
  }
}

/* 滚动条样式 */
.log-container::-webkit-scrollbar {
  width: 6px;
}

.log-container::-webkit-scrollbar-track {
  background: #f1f1f1;
  border-radius: 3px;
}

.log-container::-webkit-scrollbar-thumb {
  background: #c1c1c1;
  border-radius: 3px;
}

.log-container::-webkit-scrollbar-thumb:hover {
  background: #a8a8a8;
}

/* 响应式设计 */
@media (max-width: 1200px) {
  .main-content {
    flex-direction: column;
  }

  .jobs-section,
  .logs-section {
    width: 100%;
  }

  .jobs-section {
    height: 250px;
  }

  .logs-section {
    flex: 1;
  }

  .resource-chart {
    height: 180px;
  }

  .resource-cards {
    grid-template-columns: repeat(2, 1fr);
  }
}

@media (max-width: 768px) {
  .header-section {
    flex-direction: column;
    gap: 12px;
    align-items: stretch;
  }

  .right-monitor {
    align-items: flex-start;
  }

  .compact-monitors {
    justify-content: flex-start;
  }

  .node-info {
    flex-wrap: wrap;
    gap: 10px;
  }

  .resource-chart {
    height: 160px;
  }

  .resource-cards {
    grid-template-columns: 1fr;
  }
}
</style>
